/* TCSS 590A - Cybernetics and Systems
 * Group Project - Modeling
 * By Barry Jones, Naren Meadem, Michael Pitts, Yuan Tao
 * Fall 2012, University of Washington, Tacoma
 */
package control;

import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collection;

import output.OutPut;
import output.OutPutStream;

/**
 * A basic controller that does not run any real simulation.
 * @author Michael Pitts
 * @version Oct 30, 2012
 */
public class TestController implements Controller
{
	/** Shows that a command line argument is a type indicator.*/
	private static final String IN = "-";
	
	/** Indicates a console type output.*/
	private static final String CONSOLE = IN + "c";
	
	/** Indicates a file type output.*/
	private static final String FILE = IN + "f";
	
	/** The default new line String.*/
	private static final String NEWLINE = "\r\n";
	
	/** The default delineator String.*/
	private static final String DELINEATOR = "\t";
	
	/** Stores the command line arguments for later recall.*/
	private final String[] my_args;
	
	/** Stores all the output channels required by this Controller.*/
	private final OutPut[] my_output;
	
	/**
	 * Creates a new TestController, which stores the command line arguments.
	 * @param the_args are the command line arguments as delivered to main.
	 * @throws FileNotFoundException if a file output is indicated but the file is 
	 * not found.
	 */
	public TestController(final String[] the_args) throws FileNotFoundException
	{
		my_args = the_args;
		my_output = getOutPuts(the_args);
	}

	/**
	 * Generates one or more OutPut objects based on command line arguments.
	 * @param the_args are the arguments from the command line.
	 * @return an array of OutPut objects to be used.
	 * @throws FileNotFoundException if the indicated file is not found.
	 */
	private OutPut[] getOutPuts(final String[] the_args) throws FileNotFoundException
	{
		if (my_args != null && my_args.length > 0)
		{
			final Collection<OutPut> outputs = new ArrayList<OutPut>();
			OutPut temp; // temporarily holds potential outputs
			for (int i = 0; i< my_args.length; i++)
			{
				if (my_args[i].startsWith(IN)) 
				{
					temp = getOutPut(my_args, i);
					if (temp != null) outputs.add(temp);
				}
			}
			return outputs.toArray(new OutPut[outputs.size()]);
		} // otherwise return a default output to console
		return new OutPut[] {new OutPutStream(System.out, NEWLINE, DELINEATOR)};
	}

	/**
	 * Generates a specific output from the given String argument.
	 * @param the_args are the command line arguments.
	 * @param the_start is what index in the_args to examine.
	 * @return a new OutPut object, or null if one could not be formated from the
	 * given arguments.
	 * @throws FileNotFoundException if the indicated file is not found.
	 */
	private OutPut getOutPut(final String[] the_args, final int the_start) 
			throws FileNotFoundException
	{
		if (the_args[the_start].startsWith(FILE) && the_start+1 < the_args.length)
		{
			return setUpStream(new PrintStream(the_args[the_start+1]), the_args, the_start+2);
		}
		else if (the_args[the_start].startsWith(CONSOLE))
		{
			return setUpStream(System.out, the_args, the_start+1);
		} else 
			return null; // not an output command
	}

	/**
	 * Sets up a new OutPutStream, using the indicated stream as the core.
	 * @param the_stream is the PrintStream to wrap.
	 * @param the_args are the command line arguments which can indicate settings.
	 * @param the_index is the index on the_args where settings might begin.
	 * @return a new OutPutStream, with indicated settings or the default.
	 */
	private OutPut setUpStream(final PrintStream the_stream, 
			final String[] the_args, final int the_index)
	{
		String new_line = NEWLINE,  del = DELINEATOR;
		if (the_index < the_args.length && !the_args[the_index].startsWith(IN))
			new_line = the_args[the_index];
		if (the_index+1 < the_args.length && !the_args[the_index+1].startsWith(IN))
			del = the_args[the_index+1];
		return new OutPutStream(the_stream, new_line, del);
	}

	public void start()
	{
		if (my_args != null && my_args.length > 0)
		{
				outAll("The command line arguments were:");
				newAll();
			for (int i = 0; i < my_args.length; i++)
			{
				outAll(my_args[i]);
				newAll();
			}
		} else outAll("There were no command line arguments.");
		done();
	}

	/**
	 * Puts the indicated String to all outputs.
	 * @param the_data is the data to output.
	 */
	private void outAll(final String the_data)
	{
		for (OutPut out : my_output) out.out(the_data);
	}
	
	/**
	 * Puts a new line argument to each output.
	 */
	private void newAll()
	{
		for (OutPut out : my_output) out.newLine();
	}
	
	/**
	 * Called when the Controller is done.
	 */
	private void done()
	{
		for (OutPut out : my_output) out.close();
	}
}
